from fusionmatrix.analyzers.classifier.widget import ClassifierWidget
from fusionmatrix.base.widgets import ProgressDisplayer
from fusionmatrix.base.widgets import ExtendedSplitter, TableContainer, ExtendedTableWidget
from fusionmatrix.base.dialogs import ModelConfigDialog
from fusionmatrix.base.task import TaskExecutor
from fusionmatrix.utils import Config
from fusionmatrix.assets import get_icon_by_name

from PySide6.QtWidgets import QMainWindow, QFileDialog, QVBoxLayout, QMessageBox
from PySide6.QtGui import Qt, QDesktopServices
from PySide6.QtCore import QUrl
from pydantic import ValidationError

from typing import Optional


MANUAL_ADDR = "https://gitee.com/liyifm/fusion-matrix/wikis/FusionMatrix使用文档/FusionMatrix 0.1.0 使用手册"
ABOUT_ADDR = "https://gitee.com/liyifm/fusion-matrix"


class MainWindow(QMainWindow):

    instance: Optional['MainWindow'] = None

    def __init__(self) -> None:
        super().__init__()
        MainWindow.instance = self
        TaskExecutor.setWorkerNumber(10)

        self.setWindowTitle("FusionMatrix 0.1.0")
        self.setMinimumSize(1152, 600)
        splitter = ExtendedSplitter(Qt.Orientation.Horizontal)

        self.table_container = TableContainer()
        self.classifier_widget = ClassifierWidget()
        self.progress = ProgressDisplayer()
        TaskExecutor.progress_displayer = self.progress
        self.progress.hide()

        right_layout = QVBoxLayout()
        right_layout.setContentsMargins(0, 0, 10, self.table_container.widget_tabs.tabBar().height() - 2)
        right_layout.addWidget(self.progress)
        right_layout.addWidget(self.classifier_widget)
        splitter.addWidget(self.table_container)
        splitter.addLayout(right_layout)
        splitter.setSizes([500, 100])
        self.setCentralWidget(splitter)
        self.setWindowIcon(get_icon_by_name('fusionmatrix.png'))

        file_menu = self.menuBar().addMenu("文件")
        action_open = file_menu.addAction('打开文件')
        action_save = file_menu.addAction('保存文件')
        file_menu.addSeparator()
        action_exit = file_menu.addAction('退出')
        setting_menu = self.menuBar().addMenu("设置")
        action_model_config = setting_menu.addAction('模型管理')
        setting_menu.addSeparator()
        action_import_setting = setting_menu.addAction("导入设置")
        action_export_setting = setting_menu.addAction("导出设置")
        # setting_menu.addAction("显示调试控制台")
        help_menu = self.menuBar().addMenu("帮助")
        action_manual = help_menu.addAction("使用手册")
        action_about = help_menu.addAction("关于")

        action_open.triggered.connect(self.showOpenFileDialog)
        action_save.triggered.connect(self.showSaveFileDialog)
        action_import_setting.triggered.connect(self.showImportSettingDialog)
        action_export_setting.triggered.connect(self.showExportSettingDialog)
        action_manual.triggered.connect(lambda: QDesktopServices.openUrl(QUrl(MANUAL_ADDR)))
        action_about.triggered.connect(lambda: QDesktopServices.openUrl(QUrl(ABOUT_ADDR)))

        action_exit.triggered.connect(self.close)
        self.progress.stop_btn.clicked.connect(TaskExecutor.clearExecutor)
        action_model_config.triggered.connect(lambda: ModelConfigDialog(self).show())

        TaskExecutor.initialize()

    def closeEvent(self, event):
        super().closeEvent(event)
        TaskExecutor.shutdown()

    @classmethod
    def getActiveTable(self) -> ExtendedTableWidget:
        assert self.instance is not None
        return self.instance.table_container.activeTable()

    @classmethod
    def getTableByName(self, name: str) -> ExtendedTableWidget:
        assert self.instance is not None
        return self.instance.table_container.getTableByName(name)

    def showOpenFileDialog(self) -> None:
        file_name, _ = QFileDialog.getOpenFileName(self, "载入信息", "", "Excel Files (*.xls *.xlsx)")
        if file_name.endswith(".xls"):
            self.table_container.openExcelXlsFile(file_name)
        elif file_name.endswith(".xlsx"):
            self.table_container.openExcelXlsxFile(file_name)

    def showSaveFileDialog(self) -> None:
        file_name, _ = QFileDialog.getSaveFileName(self, "导出信息", "", "Excel Files (*.xlsx)")
        if file_name.endswith(".xls") or file_name.endswith(".xlsx"):
            self.table_container.saveExcelFile(file_name)

    def showImportSettingDialog(self) -> None:
        file_name, _ = QFileDialog.getOpenFileName(self, "载入配置文件", "", "FusionMatrix配置文件 (*.config)")
        if file_name == "":
            return

        try:
            with open(file_name, 'r', encoding='utf8') as fconfig:
                config = Config.model_validate_json(fconfig.read())
                config.save_default_config()
                QMessageBox.information(self, "配置载入成功", "配置文件已成功载入并应用 ;)")
        except ValidationError as ex:
            QMessageBox.critical(self, "无法解析配置文件", f"配置文件无法解析，这可能不是一个由FusionMatrix导出的可用配置 :(")  # type: ignore
        except Exception as ex:
            QMessageBox.critical(self, "无法载入配置文件", f"遇到了未知错误: {type(ex)}")  # type: ignore

    def showExportSettingDialog(self) -> None:
        file_name, _ = QFileDialog.getSaveFileName(self, "导出配置文件", "", "FusionMatrix配置文件 (*.config)")
        if file_name == "":
            return

        with open(file_name, 'w+', encoding='utf8') as fconfig:
            config = Config.load_default_config()
            fconfig.write(config.model_dump_json(indent=4))
